using System;
using System.Configuration;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Threading;
using System.Timers;
using System.Windows.Forms;
using SqlRunner;
using SQLRunner.gui;
using SQLRunnerLib.VersionCheck;
using Timer=System.Threading.Timer;

namespace SQLRunner
{
	/// <summary>
	/// Entry point for the SQL Server Runnner application
	/// </summary>
    public class SQLRunnerContext : ApplicationContext
	{
        
        private frmSplash splashForm;
	    private readonly ScriptsController mainScriptController;
        private frmCheckNewVersion checkVersionForm;
        private StartUpStates stage;
	    private readonly frmMain formMain;
	    private Timer timer;

        private enum StartUpStates
        {
            initial,
            splashWasCreated,
            splashWasClosed
        }

        #region Constructor
        
        public SQLRunnerContext()
		{
            // Create a new instance of a MainController
            mainScriptController = new ScriptsController();
            // Create the model
            mainScriptController.ScriptsModel = new ScriptsModel();
            // Create the view
            formMain = new frmMain();
            mainScriptController.ScriptsView = formMain;
            // Associate the model and the view
            mainScriptController.ScriptsView.Subscribe(mainScriptController.ScriptsModel);

            // Hook the form events to this class methods
            formMain.VisibleChanged += OnMainVisibleChanged;
            formMain.Closed += OnMainClosed;
            // Start main form
            stage = StartUpStates.initial;
            MainForm = formMain;
        }

	    #endregion
        #region Splash Methods

        private void StartSplash()
        {
            // Instance a splash form given the image names
            splashForm = new frmSplash();
            splashForm.VisibleChanged += OnSplashVisibleChanged;
            Application.Run(splashForm);
        }

        private void CloseSplash(object source)
        {
            if (splashForm == null) return;
            // Shut down the splash screen
            timer.Dispose();
            timer = null;
            splashForm.Invoke(new EventHandler(splashForm.KillMe));
            splashForm.Dispose();
            splashForm = null;         
        }
        
        #endregion
        #region Handler Events

        private void OnMainClosed(object sender, EventArgs e)
        {
            Application.Exit();
        }

	    private void OnMainVisibleChanged(object sender, EventArgs e)
	    {
            if ( stage == StartUpStates.initial)
            {              
                Thread splashThread = new Thread(StartSplash);
                splashThread.Start();
                stage = StartUpStates.splashWasCreated;                
            }
            if (stage == StartUpStates.splashWasCreated && formMain.Visible)
            {
                formMain.Shown -= OnMainVisibleChanged;             
                timer = new Timer(CloseSplash, MainForm, 1000, 3000);
                stage = StartUpStates.splashWasClosed;
                formMain.Focus();
            }
                             	           
	    }

        private void OnSplashVisibleChanged(object sender, EventArgs e)
        {
            splashForm.VisibleChanged -= OnSplashVisibleChanged;
            CheckForNewVersion();
        }

        #endregion
        #region Check For New Version

        private void CheckForNewVersion()
        {          
            bool flag = bool.Parse(ConfigurationManager.AppSettings.Get("CheckForNewVersion"));
            if (!flag) return;
            URLChecker checker = new URLChecker();
            CheckVersionHandler checkerCall = checker.CheckVersion;
            checkerCall.BeginInvoke(
                ConfigurationManager.AppSettings.Get("NewVersionUrl"),
                Assembly.GetExecutingAssembly().GetName().Version,
                AsyncCheckVersion, null);
        }

        private void AsyncCheckVersion(IAsyncResult receipt)
        {
            AsyncResult result = (AsyncResult)receipt;
            //  retrieve the calling delegate
            CheckVersionHandler checkerCall = (CheckVersionHandler)result.AsyncDelegate;
            //  Retrieve our results; this is guaranteed not to block, as the async op is complete
            SQLRunnerVersion webVersion = checkerCall.EndInvoke(receipt);
            if (webVersion != null)
            {
                bool flag = webVersion.Version.CompareTo(
                                AppVersion.ConvertFromSystemVersion(
                                    Assembly.GetExecutingAssembly().GetName().Version)) > 0;
                if (!flag) return;
                checkVersionForm =
                    new frmCheckNewVersion(
                    webVersion.MsiUrl,
                    AppVersion.TransforToSystemVersion(webVersion.Version),
                    webVersion.LinkText);
                Application.Run(checkVersionForm);
            }
        }

        #endregion

	    [STAThread]
		static void Main(string[] args) 
		{
            Application.EnableVisualStyles();
	        Application.Run(new SQLRunnerContext());
		}
	}
}
